﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Gnosis.Alexandria.Model.Repositories;

namespace Gnosis.Alexandria.Model
{
    public abstract class IdentifiableBase
        : IIdentifiable
    {
        private long _id;
        private bool _isDeleted;
        private readonly IDictionary<string, object> _changes = new Dictionary<string, object>();

        public abstract string RecordName { get; }

        protected virtual void AddChange(string name, object value)
        {
            _changes[name] = value;
        }

        protected virtual void InitializeField(string fieldName, object value)
        {
            if (fieldName == "Id")
                _id = (long)value;
        }

        #region IIdentifiable Members

        public long Id
        {
            get { return _id; }
        }

        public bool IsChanged
        {
            get { return _changes.Count > 0; }
        }

        public bool IsDeleted
        {
            get { return _isDeleted; }
        }

        public bool IsNew
        {
            get { return _id == 0; }
        }

        public IRepository Repository
        {
            get;
            set;
        }

        public IDictionary<string, object> Changes()
        {
            return _changes;
        }

        public void Delete()
        {
            if (!_isDeleted)
                _isDeleted = true;
            else throw new InvalidOperationException("This record is already marked as deleted");
        }

        public void Initialize(IDictionary<string, object> data)
        {
            if (_id != 0)
                throw new InvalidOperationException("This record is already initialized");

            if (data != null)
                foreach (KeyValuePair<string, object> pair in data)
                    InitializeField(pair.Key, pair.Value);
        }

        #endregion

        #region IEquatable<IIdentifiable> Members

        public bool Equals(IIdentifiable other)
        {
            if (object.ReferenceEquals(this, other))
                return true;

            if (object.ReferenceEquals(other, null))
                return false;

            if (this.GetType().Name == other.GetType().Name)
            {
                return this.Id == other.Id;
            }

            return false;
        }

        #endregion
    }
}
